package com.springinpractice.ch07.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
import org.apache.jackrabbit.ocm.manager.impl.ObjectContentManagerImpl;
import org.apache.jackrabbit.ocm.mapper.Mapper;
import org.hibernate.Session;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.extensions.jcr.SessionFactory;
import org.springframework.extensions.jcr.SessionFactoryUtils;
import javax.

public abstract class AbstractJcrDao<T> implements Dao<T>, ImportingDao<T>,
		ExportingDao<T>
{
	private Class<T> domainClass;
	private String nodeName;
	@Inject
	private SessionFactory sessionFactory;
	@Inject
	private Mapper mapper;

	public AbstractJcrDao(String nodeName)
	{
		this.nodeName = nodeName;
	}

	private Class<T> getDomainClass()
	{
		if (domainClass == null)
		{
			ParameterizedType thisType = (ParameterizedType) getClass()
					.getGenericSuperclass();
			this.domainClass = (Class<T>) ((ParameterizedType) thisType).getActualTypeArguments()[0];
		}
		return domainClass;
	}

	public String getNodeName()
	{
		return nodeName;
	}

	public String getNodePath()
	{
		return "/" + nodeName;
	}

	protected Session getSession()
	{
		return getSession(false);
	}

	protected Session getSession(boolean allowCreate)
	{
		return (Session) SessionFactoryUtils.getSession(sessionFactory, allowCreate);
	}

	protected ObjectContentManager getOcm()
	{
		return new ObjectContentManagerImpl((javax.jcr.Session) getSession(), mapper);
	}

	protected String toPath(Serializable id)
	{
		return getNodePath() + "/" + id;
	}

	public T get(Serializable id)
	{
		T obj = (T) getOcm().getObject(getDomainClass(), toPath(id));
		if (obj != null)
		{
			return obj;
		}
		else
		{
			throw new DataRetrievalFailureException("No such object: "
					+ getDomainClass() + ", id=" + id);
		}
	}
	// ... various other methods ...
}